package cn.eeepay.framework.service.impl;

import cn.eeepay.framework.dao.PolicyTargetDao;
import cn.eeepay.framework.dao.sysUser.SysConfigDao;
import cn.eeepay.framework.db.pagination.Page;
import cn.eeepay.framework.model.*;
import cn.eeepay.framework.org.*;
import cn.eeepay.framework.service.PolicyTargetService;
import cn.eeepay.framework.util.BossBaseException;
import cn.eeepay.framework.util.DateUtils;
import cn.eeepay.framework.util.ListDataExcelExport;
import cn.eeepay.framework.util.StringUtil;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigInteger;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
@Transactional
public class PolicyTargetServiceImpl implements PolicyTargetService {

    private static final String TARGET_CONFIG_KEY = "policy_target_config";

    private static final Logger log = LoggerFactory.getLogger(PolicyTargetServiceImpl.class);

    @Resource
    private PolicyTargetDao ptDao;
    @Resource
    private SysConfigDao sysConfigDao;

    @Override
    public List<PolicyTargetDetail> selectPolicyTargetDetail(BigInteger policyTargetRecordId) {
        List<PolicyTargetDetail> list = ptDao.selectPolicyTargetDetail(policyTargetRecordId);
        Map<String, String> routeTypes = new HashMap<>();
        routeTypes.put("pos", "普通收款");
        routeTypes.put("youxiang", "优享收款");

        Map<String, String> statuses = new HashMap<>();
        statuses.put("0", "未生效");
        statuses.put("1", "已生效");

        for (PolicyTargetDetail detail : list) {
            detail.setRouteTypeStr(StringUtil.filterNull(routeTypes.get(detail.getRouteType())));
            detail.setStatusStr(StringUtil.filterNull(statuses.get(detail.getStatus())));
        }
        return list;
    }

    @Override
    public void export(HttpServletResponse response, PolicyTarget target) {
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd") ;
        SimpleDateFormat sdf2 = new SimpleDateFormat("HH:mm:ss") ;
        SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") ;
        SimpleDateFormat sdf4 = new SimpleDateFormat("yyyyMMddHH:mm:ss") ;
        OutputStream ouputStream = null;
        try {
            Page<PolicyTarget> page = new Page<>(0, Integer.MAX_VALUE);
            list(target, page);
            List<PolicyTarget> list = page.getResult();
            int size = 2;
            ListDataExcelExport export = new ListDataExcelExport(size);
            String fileName = "目标金额配置" + sdf4.format(new Date()) + export.getFileSuffix(size);
            String fileNameFormat = new String(fileName.getBytes(),"ISO-8859-1");
            response.setHeader("Content-disposition", "attachment;filename="+fileNameFormat);
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            List<Map<String, String>> data = new ArrayList<>();

            Map<String, String> categories = new HashMap<>();
            categories.put("1", "同旬同类");
            categories.put("2", "同旬不限类");
            categories.put("3", "不限旬不限类");

            Map<String, String> categoryTypes = new HashMap<>();
            categoryTypes.put("1", "最高值");
            categoryTypes.put("2", "平均值");
            categoryTypes.put("3", "最低值");

            for(PolicyTarget item: list){
                Map<String,String> map = new HashMap<>();

                map.put("createDate", sdf1.format(item.getCreateDate()));
                map.put("mTime", sdf2.format(item.getmTime()));

                map.put("vipCategory", categories.get(item.getVipCategory()));
                map.put("vipCategoryType", categoryTypes.get(item.getVipCategoryType()));
                map.put("forecastVipRatio", StringUtil.filterNull(item.getForecastVipRatio()));
                map.put("actualVipRatio", StringUtil.filterNull(item.getActualVipRatio()));
                map.put("forecastVipAmount", StringUtil.filterNull(item.getForecastVipAmount()));
                map.put("actualVipAmount", StringUtil.filterNull(item.getActualVipAmount()));
                map.put("timeActualVipAmount", StringUtil.filterNull(item.getTimeActualVipAmount()));

                map.put("nonCategory", categories.get(item.getNonCategory()));
                map.put("nonCategoryType", categoryTypes.get(item.getNonCategoryType()));
                map.put("forecastNonRatio", StringUtil.filterNull(item.getForecastNonRatio()));
                map.put("actualNonRatio", StringUtil.filterNull(item.getActualNonRatio()));
                map.put("forecastNonAmount", StringUtil.filterNull(item.getForecastNonAmount()));
                map.put("actualNonAmount", StringUtil.filterNull(item.getActualNonAmount()));
                map.put("timeActualNonAmount", StringUtil.filterNull(item.getTimeActualNonAmount()));

                map.put("transCategory", categories.get(item.getTransCategory()));
                map.put("transCategoryType", categoryTypes.get(item.getTransCategoryType()));
                map.put("forecastTransRatio", StringUtil.filterNull(item.getForecastTransRatio()));
                map.put("actualTransRatio", StringUtil.filterNull(item.getActualTransRatio()));
                map.put("forecastTransAmount", StringUtil.filterNull(item.getForecastTransAmount()));
                map.put("actualTransAmount", StringUtil.filterNull(item.getActualTransAmount()));
                map.put("timeActualTransAmount", StringUtil.filterNull(item.getTimeActualTransAmount()));

                map.put("useStatus", "1".equals(item.getUseStatus()) ? "未使用" : "已使用");
                map.put("lastUpdateTime", sdf3.format(item.getLastUpdateTime()));
                map.put("bySource", item.getBySource());

                map.put("remark", StringUtil.filterNull(item.getRemark()));

                data.add(map);
            }
            String[] cols = new String[]{
                    "createDate","mTime",
                    "vipCategory","vipCategoryType","forecastVipRatio","actualVipRatio","forecastVipAmount","actualVipAmount","timeActualVipAmount",
                    "nonCategory","nonCategoryType","forecastNonRatio","actualNonRatio","forecastNonAmount","actualNonAmount","timeActualNonAmount",
                    "transCategory","transCategoryType","forecastTransRatio","actualTransRatio","forecastTransAmount","actualTransAmount","timeActualTransAmount",
                    "useStatus","lastUpdateTime","bySource",
                    "remark"
            };
            String[] colsName = new String[]{
                    "预估日期","预估时间",
                    "VIP类别","VIP类型","预测VIP占比值","实际VIP占比值","预估VIP交易量","实际VIP交易量","VIP截止预估时间交易量",
                    "非优享类别","非优享类型","预测非优享占比值","实际非优享占比值","预估非优享交易量","实际非优享交易量","非优享截止预估时间交易量",
                    "总量类别","总量类型","预测总量占比值","实际总量占比值","预估总量交易量","实际总量交易量","总量截止预估时间交易量",
                    "状态","更新时间","来源",
                    "备注"
            };
            ouputStream = response.getOutputStream();
            export.export(cols, colsName, data, response.getOutputStream());
        } catch (Exception e) {
            log.error("目标金额配置导出异常", e);
        } finally {
            if(ouputStream!=null){
                try {
                    ouputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /** 上旬 */
    private static final int XUN_EARLY  = 10;
    /** 中旬 */
    private static final int XUN_MID  = 20;

    /**
     * 获取日期data，是工作日还是周末
     * 1 工作，2 周末
     * @author tans
     * @date 2020/12/28 14:39
     * @param
     * @return
     */
    public static int getHolidayType(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        //星期六、星期天,返回周末
        if (dayOfWeek == Calendar.SUNDAY || dayOfWeek == Calendar.SATURDAY) {
            return 2;
        }
        return 1;
    }

    /**
     * 获取日期data，是上旬、中旬、下旬
     * 1 上旬，2 下旬， 3 上旬
     * @author tans
     * @date 2020/12/28 14:39
     * @param
     * @return
     */
    public static int getXunType(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
        //星期六、星期天,返回周末
        if (dayOfMonth <= XUN_EARLY) {
            return 1;
        }
        if (dayOfMonth > XUN_EARLY && dayOfMonth <= XUN_MID ) {
            return 2;
        }
        if (dayOfMonth > XUN_MID) {
            return 3;
        }
        return 0;
    }

    @Override
    public void savePolicyTarget(PolicyTarget target) {
        final UserLoginInfo principal = (UserLoginInfo) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        target.setBySource(principal.getUsername());
        target.setOperator(principal.getUsername());

        String time = DateUtils.format(target.getCreateDate(), "yyyy-MM-dd") + " " + target.getmTimeStr() + ":00";
        Date updateTime = DateUtils.parseDateTime(time);
        if(updateTime.before(new Date())){
            throw new BossBaseException("更新时间不能小于当前时间");
        }

        target.setXunType(getXunType(target.getCreateDate()));
        target.setHolidayType(getHolidayType(target.getCreateDate()));
        try {
            target.setmTime(new SimpleDateFormat("HH:mm").parse(target.getmTimeStr()));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        if(null != target.getId()){
            int num = ptDao.selectPolicyTargetDetailByTimeAndId(DateUtils.format(target.getCreateDate(), "yyyy-MM-dd"), target.getmTimeStr(), target.getId());
            if(num > 0){
                throw new BossBaseException("更新时间已存在");
            }
            ptDao.updatePolicyTarget(target);
        }else {
            int num = ptDao.selectPolicyTargetDetailByTime(DateUtils.format(target.getCreateDate(), "yyyy-MM-dd"), target.getmTimeStr());
            if(num > 0){
                throw new BossBaseException("更新时间已存在");
            }
            ptDao.savePolicyTarget(target);
        }

    }

    @Override
    public List<PolicyTarget> list(PolicyTarget target, Page<PolicyTarget> page) {
        ptDao.list(target, page);
        return page.getResult();
    }

    @Override
    public List<PolicyQuotaInfo> selectHisQuotas(Page<PolicyQuotaInfo> page) {
        ptDao.selectHisQuotas(page);
        return page.getResult();
    }

    @Override
    public List<PolicyQuotaInfo> selectNewQuotas() {
        return ptDao.selectNewQuotas();
    }

    @Override
    public List<PolicyMTime> selectMTimes() {
        return ptDao.selectMTimes();
    }


    @Override
    public void saveMTimes(List<PolicyMTime> mTimes) {
        final UserLoginInfo principal = (UserLoginInfo) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        ptDao.deleteAll();
        for (PolicyMTime mTime : mTimes) {
            int num = ptDao.selectMTimeByMTime(mTime.getmTime());
            if(num > 0){
                throw new BossBaseException("生效时间不能相同");
            }
            mTime.setOperator(principal.getUsername());
            ptDao.saveMTime(mTime);
        }
        //ptDao.batchInsert(mTimes);
    }

    @Override
    public void saveQuotas(List<PolicyQuotaInfo> quotas) {
        final UserLoginInfo principal = (UserLoginInfo) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        ptDao.deleteQuota();
        for (PolicyQuotaInfo quota : quotas) {
            // 判断生效时间是否存在
            int num = ptDao.selectQuotaInfoByEffective(quota.getEffectiveTime());
            if(num > 0){
                throw new BossBaseException("生效时间不能相同");
            }
            quota.setOperator(principal.getUsername());
            ptDao.saveNewQuota(quota);
        }
    }

    @Override
    public PolicyTarget selectPolicyTarget(BigInteger id) {
        return ptDao.selectPolicyTarget(id);
    }

    @Override
    public int deletePolicyTarget(BigInteger id) {
        return ptDao.deletePolicyTarget(id);
    }


    @Override
    public void updateTargetConfig(String param) {
        sysConfigDao.updateConfigByKey(TARGET_CONFIG_KEY, param);
    }

    @Override
    public void updateTargetRange(PolicyTargetRange config) {
        sysConfigDao.updateConfigByKey("policy_target_vip_range", JSONObject.toJSONString(config.getVip()));
        sysConfigDao.updateConfigByKey("policy_target_non_range", JSONObject.toJSONString(config.getNon()));
        sysConfigDao.updateConfigByKey("policy_target_trans_range", JSONObject.toJSONString(config.getTrans()));
    }

    @Override
    public String selectTargetConfig() {
        return sysConfigDao.getStringValueByKey(TARGET_CONFIG_KEY);
    }

    @Override
    public PolicyTargetRange selectTargetRange() {
        Vip vip =  JSONObject.parseObject(sysConfigDao.getStringValueByKey("policy_target_vip_range"), Vip.class);
        Non non =  JSONObject.parseObject(sysConfigDao.getStringValueByKey("policy_target_non_range"), Non.class);
        Trans trans =  JSONObject.parseObject(sysConfigDao.getStringValueByKey("policy_target_trans_range"), Trans.class);
        return new PolicyTargetRange(vip, non, trans);
    }
}
